package com.cskaoyan.market.admin.service.impl;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.ibatis.session.SqlSession;

import com.cskaoyan.market.admin.service.AdminStatService;
import com.cskaoyan.market.db.domain.*;
import com.cskaoyan.market.db.mapper.MarketOrderGoodsMapper;
import com.cskaoyan.market.db.mapper.MarketOrderMapper;
import com.cskaoyan.market.db.mapper.MarketUserMapper;
import com.cskaoyan.market.util.MyBatisUtil;

/**
 * @author BlackFlame33
 * @date 2023/03/22
 **/
public class AdminStatServiceImpl implements AdminStatService {
    @Override
    public Map<String, Object> getUserStat() {
        SqlSession session = MyBatisUtil.getSession();
        MarketUserMapper mapper = session.getMapper(MarketUserMapper.class);
        List<MarketUser> marketUsers =
            mapper.selectByExampleSelective(new MarketUserExample(), MarketUser.Column.addTime);
        List<Map<String, Object>> rows = new LinkedList<>();
        Map<String, Object> row;
        for (MarketUser user : marketUsers) {
            row = new HashMap<>();
            LocalDate addDate = user.getAddTime().toLocalDate();
            long users = mapper.countByExample(new MarketUserExample().or()
                .andAddTimeBetween(addDate.atStartOfDay(), addDate.plusDays(1).atStartOfDay()).example());
            row.put("day", addDate);
            row.put("users", users);
            rows.add(row);
        }
        Map<String, Object> data = new HashMap<>();
        data.put("columns", Stream.of("day", "users").collect(Collectors.toList()));
        data.put("rows", rows);
        return data;
    }

    @Override
    public Map<String, Object> getOrderStat() {
        SqlSession session = MyBatisUtil.getSession();
        MarketOrderMapper orderMapper = session.getMapper(MarketOrderMapper.class);
        MarketOrderGoodsMapper orderGoodsMapper = session.getMapper(MarketOrderGoodsMapper.class);
        List<MarketOrder> marketOrders = orderMapper.selectByExample(new MarketOrderExample());
        Set<String> daySet = new HashSet<>();
        Map<String, Object> data = new HashMap<>();
        List<Map<String, Object>> rows = new LinkedList<>();
        for (MarketOrder marketOrder : marketOrders) {
            LocalDate day = marketOrder.getAddTime().toLocalDate();
            daySet.add(String.valueOf(day));
        }
        for (String day : daySet) {
            Map<String, Object> row = new HashMap<>();
            row.put("day", day);
            long customers = 0;
            long orders;
            BigDecimal amount = BigDecimal.valueOf(0);
            for (MarketOrder marketOrder : marketOrders) {
                List<MarketOrderGoods> orderGoods = orderGoodsMapper.selectByExample(
                    new MarketOrderGoodsExample().or().andOrderIdEqualTo(marketOrder.getId()).example());
                for (MarketOrderGoods orderGood : orderGoods) {
                    amount = amount.add(orderGood.getPrice().multiply(BigDecimal.valueOf(orderGood.getNumber())));
                }
            }

            LocalDateTime startDay = LocalDate.parse(day).atStartOfDay();
            LocalDateTime endDay = LocalDate.parse(day).plusDays(1).atStartOfDay();
            orders =
                orderMapper.countByExample(new MarketOrderExample().or().andAddTimeBetween(startDay, endDay).example());
            customers =
                orderMapper.countByExample(new MarketOrderExample().or().andAddTimeBetween(startDay, endDay).example());
            row.put("amount", amount);
            row.put("orders", orders);
            row.put("customers", customers);
            row.put("pcr", amount);
            rows.add(row);
        }
        data.put("columns", Stream.of("day", "users", "customers", "pcr").collect(Collectors.toList()));
        data.put("rows", rows);
        session.commit();
        session.close();
        return data;
    }

    @Override
    public Map<String, Object> getGoodStat() {
        SqlSession session = MyBatisUtil.getSession();
        MarketOrderMapper orderMapper = session.getMapper(MarketOrderMapper.class);
        MarketOrderGoodsMapper orderGoodsMapper = session.getMapper(MarketOrderGoodsMapper.class);
        List<MarketOrder> marketOrders = orderMapper.selectByExample(new MarketOrderExample());
        Set<String> daySet = new HashSet<>();
        Map<String, Object> data = new HashMap<>();
        List<Map<String, Object>> rows = new LinkedList<>();
        for (MarketOrder marketOrder : marketOrders) {
            LocalDate day = marketOrder.getAddTime().toLocalDate();
            daySet.add(String.valueOf(day));
        }
        for (String day : daySet) {
            Map<String, Object> row = new HashMap<>();
            row.put("day", day);
            long products = 0;
            long orders;
            BigDecimal amount = BigDecimal.valueOf(0);
            for (MarketOrder marketOrder : marketOrders) {
                List<MarketOrderGoods> orderGoods = orderGoodsMapper.selectByExample(
                        new MarketOrderGoodsExample().or().andOrderIdEqualTo(marketOrder.getId()).example());
                for (MarketOrderGoods orderGood : orderGoods) {
                    amount = amount.add(orderGood.getPrice().multiply(BigDecimal.valueOf(orderGood.getNumber())));
                }
            }

            LocalDateTime startDay = LocalDate.parse(day).atStartOfDay();
            LocalDateTime endDay = LocalDate.parse(day).plusDays(1).atStartOfDay();
            orders =
                    orderMapper.countByExample(new MarketOrderExample().or().andAddTimeBetween(startDay, endDay).example());
            products =
                    orderMapper.countByExample(new MarketOrderExample().or().andAddTimeBetween(startDay, endDay).example());
            row.put("amount", amount);
            row.put("orders", orders);
            row.put("products", products);
            rows.add(row);
        }
        data.put("columns", Stream.of("day", "orders", "products", "amount").collect(Collectors.toList()));
        data.put("rows", rows);
        session.commit();
        session.close();
        return data;
    }
}